gusucode.com > VC++视频目标检测演示帧间差分法-源码程序 > VC++视频目标检测演示帧间差分法-源码程序/code/Video Demo/GravityCenter.cpp
//Download by http://www.NewXing.com /******************************************************* Motion target detection & tracking by gravity center Author: jianglong date: 2006.08 Compiler: Microsoft Visual C++ 6.0 *******************************************************/ #include "stdafx.h" #include <math.h> #include "GravityCenter.h" CGravityCenter::CGravityCenter(int nwidth,int nheight) { m_otype = TRUE; m_width = nwidth; m_height = nheight; m_imageSize = m_width*m_height; m_threshBH = S_THRESHOLD_BH; m_threshW = S_THRESHOLD_TR; permitflag1=FALSE; permitflag2=FALSE; permitflag3=FALSE; permitflag4=FALSE; captureflag1=FALSE; captureflag2=FALSE; captureflag3=FALSE; captureflag4=FALSE; m_threshBHD = THRESHOLD_BH; m_threshW1 = THRESHOLD_TR; m_threshW2 = THRESHOLD_TR; m_threshW3 = THRESHOLD_TR; m_threshW4 = THRESHOLD_TR; m_CurImage = new unsigned char[m_imageSize*3]; m_CurGrayImage = new unsigned char[m_imageSize]; m_TempGrayImage = new unsigned char[m_imageSize]; m_PreGrayImage = new unsigned char[m_imageSize]; memset(m_CurImage,0,m_imageSize*3); memset(m_CurGrayImage,0,m_imageSize); memset(m_PreGrayImage,0,m_imageSize); memset(m_TempGrayImage,0,m_imageSize); } CGravityCenter::~CGravityCenter() { delete []m_PreGrayImage; delete []m_CurGrayImage; delete []m_TempGrayImage; delete []m_CurImage; } void CGravityCenter::Initial() { m_colorType = 0; m_TargetWin.pt.x=150; m_TargetWin.pt.y=100; m_TargetWin.w = 40; m_TargetWin.h = 40; m_TargetWin.flag = FALSE; m_DrawWin.pt.x=m_width/2; m_DrawWin.pt.y=m_height/2; m_DrawWin.w = (m_width-4)/3; m_DrawWin.h = (m_height-4)/3; m_DrawWin.flag = FALSE; } void CGravityCenter::InitalObjectTracker(BOOL type, int threshold) { trackflag = FALSE; m_otype = type; m_threshold = threshold; } void CGravityCenter::GravityCenter(int index, unsigned char *nRGBbuffer) { m_frame = index; memcpy(m_CurImage,nRGBbuffer,m_width*m_height*3); RGBToGray(m_CurImage,m_CurGrayImage,m_width,m_height); if(false) //单目标 { if(!trackflag) { Initial(); switch(m_threshold)//捕获阈值选取 { case 0: m_threshBH = S_THRESHOLD_BH; break; case 1: m_threshBH = GetBHThByHistogram(m_CurGrayImage,m_width,m_height); break; default: break; } m_TargetWin = gravity(m_CurGrayImage, m_width, m_height, m_threshBH); trackflag = m_TargetWin.flag; } else { switch(m_threshold)//跟踪窗内阈值选取 { case 0: m_threshW = S_THRESHOLD_TR; break; case 1: m_threshW = GetWThByHistogram(m_CurGrayImage, m_TargetWin, m_width, m_height); break; default: break; } m_TargetWin = AdjustWindow(m_TargetWin, m_width, m_height); m_TargetWin = gvtrack(m_CurGrayImage, m_width, m_height, m_TargetWin, m_threshW); trackflag = m_TargetWin.flag; } if(trackflag) { m_DrawWin = AdjustWindow(m_TargetWin, m_width, m_height); m_result.frame = index; m_result.x = (short)m_DrawWin.pt.x; m_result.y = (short)m_DrawWin.pt.y; m_result.w = m_DrawWin.w; m_result.h = m_DrawWin.h; } DrawObjectBox(nRGBbuffer, m_DrawWin); } else //多目标 { Initial(); switch(m_threshold)//捕获阈值选取 { case 0: m_threshBHD = THRESHOLD_BH; break; case 1: m_threshBHD = GetBHThByHistogram(m_CurGrayImage,m_width,m_height); break; default: break; } if(permitflag1==1) { m_TargetWin1 = AdjustWindow(m_TargetWin1, m_width, m_height); // m_threshW1 = GetWThByHistogram(m_CurGrayImage,m_TargetWin1,m_width, m_height); // m_threshW1 = threshold_area(m_CurGrayImage,m_TargetWin1,m_width, m_height); m_TargetWin1 = gvtrack(m_CurGrayImage, m_width, m_height, m_TargetWin1, m_threshW1); captureflag1 = m_TargetWin1.flag; if(captureflag1 == 1) { m_ObjectNum++; m_DrawWin1 = AdjustWindow(m_TargetWin1, m_width, m_height); erasure(m_CurGrayImage, m_DrawWin1, m_width, m_height); DrawObjectBox(nRGBbuffer, m_DrawWin1); } else { permitflag1 = 0; } } if(permitflag2==1) { m_TargetWin2 = AdjustWindow(m_TargetWin2, m_width, m_height); //m_threshW2 = GetWThByHistogram(m_CurGrayImage, m_TargetWin2, m_width, m_height); //m_threshW2 = threshold_area(m_CurGrayImage,m_TargetWin2,m_width, m_height); m_TargetWin2 = gvtrack(m_CurGrayImage, m_width, m_height, m_TargetWin2, m_threshW2); captureflag2 = m_TargetWin2.flag; if(captureflag2 == 1) { m_ObjectNum++; m_DrawWin2 = AdjustWindow(m_TargetWin2, m_width, m_height); erasure(m_CurGrayImage, m_DrawWin2, m_width, m_height); DrawObjectBox(nRGBbuffer, m_DrawWin2); } else { permitflag2 = 0; } } if(permitflag3==1) { m_TargetWin3 = AdjustWindow(m_TargetWin3, m_width, m_height); // m_threshW3 = GetWThByHistogram(m_CurGrayImage,m_TargetWin3,m_width, m_height); // m_threshW3 = threshold_area(m_CurGrayImage,m_TargetWin3,m_width, m_height); m_TargetWin3 = gvtrack(m_CurGrayImage, m_width, m_height, m_TargetWin3, m_threshW3); captureflag3 = m_TargetWin3.flag; if(captureflag3 == 1) { m_ObjectNum++; m_DrawWin3 = AdjustWindow(m_TargetWin3, m_width, m_height); erasure(m_CurGrayImage, m_DrawWin3, m_width, m_height); DrawObjectBox(nRGBbuffer, m_DrawWin3); } else { permitflag3 = 0; } } if(permitflag4==1) { m_TargetWin4 = AdjustWindow(m_TargetWin4, m_width, m_height); // m_threshW4 = GetWThByHistogram(m_CurGrayImage,m_TargetWin4,m_width, m_height); // m_threshW4 = threshold_area(m_CurGrayImage,m_TargetWin4,m_width, m_height); m_TargetWin4 = gvtrack(m_CurGrayImage, m_width, m_height, m_TargetWin4, m_threshW4); captureflag4 = m_TargetWin4.flag; if(captureflag4 == 1) { m_ObjectNum++; m_DrawWin4 = AdjustWindow(m_TargetWin4, m_width, m_height); erasure(m_CurGrayImage, m_DrawWin4, m_width, m_height); DrawObjectBox(nRGBbuffer, m_DrawWin4); } else { permitflag4 = 0; } } //捕获过程 if(permitflag1==0) { m_TargetWin1 = findEdge(m_CurGrayImage, m_width, m_height, m_threshBHD, BLOCK_NUMBER); permitflag1 = m_TargetWin1.flag; } else if(permitflag2==0) { m_TargetWin2 = findEdge(m_CurGrayImage, m_width, m_height, m_threshBHD, BLOCK_NUMBER); permitflag2 = m_TargetWin2.flag; } else if(permitflag3==0) { m_TargetWin3 = findEdge(m_CurGrayImage, m_width, m_height, m_threshBHD, BLOCK_NUMBER); permitflag3 = m_TargetWin3.flag; } else if(permitflag4==0) { m_TargetWin4 = findEdge(m_CurGrayImage, m_width, m_height, m_threshBHD, BLOCK_NUMBER); permitflag4 = m_TargetWin4.flag; } else return; m_result.frame = index; m_result.x = 0; m_result.y = 0; m_result.w = 0; m_result.h = 0; } } //灰度化 void CGravityCenter::RGBToGray(unsigned char *sRGB, unsigned char *sGray, int nWidth, int nHeight) { int i,j; for(j=0;j<nHeight;j++) { for(i=0;i<nWidth;i++) { int k = nWidth*j+i; sGray[k]=(11*sRGB[3*k]+59*sRGB[3*k+1]+30*sRGB[3*k+2])/100; } } } //二值化 void CGravityCenter::Segment(unsigned char *sGray, int nWidth, int nHeight, int nThreshold) { int i,j; for(j=0;j<nHeight;j++) { for(i=0;i<nWidth;i++) { int k = nWidth*j+i; if(sGray[k]>nThreshold) sGray[k] = 1; else sGray[k] = 0; } } } //图像反色 void CGravityCenter::Inverse(unsigned char *sGray, int nWidth, int nHeight) { int i,j; for(j=0;j<nHeight;j++) { for(i=0;i<nWidth;i++) { int k = nWidth*j+i; sGray[k] = unsigned char(255-sGray[k]); } } } //选取跟踪窗口颜色 unsigned long CGravityCenter::GetBoxColor() { unsigned long pixelValues = 0; switch(m_colorType) { case 0: pixelValues = RGB(255,0,0); break; case 1: pixelValues = RGB(0,255,0); break; case 2: pixelValues = RGB(0,0,255); break; case 3: pixelValues = RGB(255,255,0); break; case 4: pixelValues = RGB(255,0,255); break; case 5: pixelValues = RGB(0,255,255); break; case 6: pixelValues = RGB(255,255,255); break; case 7: pixelValues = RGB(128,0,128); break; case 8: pixelValues = RGB(128,128,0); break; case 9: pixelValues = RGB(128,128,128); break; case 10: pixelValues = RGB(255,128,0); break; case 11: pixelValues = RGB(0,128,128); break; case 12: pixelValues = RGB(123,50,10); break; case 13: pixelValues = RGB(10,240,126); break; case 14: pixelValues = RGB(0,128,255); break; case 15: pixelValues = RGB(128,200,20); break; default: break; } return(pixelValues); } //改变窗口颜色 void CGravityCenter::SetPixelValues(unsigned char *sRGB,unsigned long pixelValues, int x, int y) { *(sRGB+(y*m_width+x)*3+2) = unsigned char(pixelValues & 0xFF); *(sRGB+(y*m_width+x)*3+1) = unsigned char((pixelValues >> 8) & 0xFF); *(sRGB+(y*m_width+x)*3) = unsigned char((pixelValues >> 16) & 0xFF); } //画跟踪窗口 void CGravityCenter::DrawObjectBox(unsigned char *sRGB, WININFO sWin) { int i,j; unsigned long pv=0; pv = GetBoxColor(); for(i=sWin.pt.x-sWin.w; i<sWin.pt.x+sWin.w; i++) { SetPixelValues(sRGB,pv,i,sWin.pt.y-sWin.h); SetPixelValues(sRGB,pv,i,sWin.pt.y+sWin.h); } for(j=sWin.pt.y-sWin.h; j<sWin.pt.y+sWin.h; j++) { SetPixelValues(sRGB,pv,sWin.pt.x-sWin.w,j); SetPixelValues(sRGB,pv,sWin.pt.x+sWin.w,j); } } //直方图法求捕获阈值 int CGravityCenter::GetBHThByHistogram(unsigned char *sGray,int nWidth, int nHeight) { int threshold; int mean=0; int grayMax=0; int calHistNum=0; int whiteContrast=0; int i,j,tmp; int his[256]; for(i= 0;i<256;i++) his[i] = 0; //calculate the histogram of image for(i=EDGE_SPACE;i<nHeight-EDGE_SPACE;i++) { for(j=EDGE_SPACE;j<nWidth-EDGE_SPACE;j++) { tmp = sGray[i*nWidth+j]; his[tmp]++; if(tmp>grayMax) grayMax = tmp; } } //calculate the contrast of image calHistNum = (nWidth-2*EDGE_SPACE)*(nHeight-2*EDGE_SPACE); for(i= 0;i<256;i++) { mean+=his[i]*i; } mean = mean/calHistNum; whiteContrast = 100*(grayMax-mean)/grayMax; if(whiteContrast>30) threshold = grayMax-50; else if (whiteContrast>27) threshold = grayMax-30; else if (whiteContrast>24) threshold = grayMax-20; else if (whiteContrast>20) threshold = grayMax-15; else if (whiteContrast>9) threshold = grayMax-11; else if (whiteContrast>4) threshold = grayMax-6; else threshold = grayMax; return threshold; } //直方图法求窗口内阈值 int CGravityCenter::GetWThByHistogram(unsigned char *sGray, WININFO sWin, int nWidth, int nHeight) { int threshold; int mean=0; int grayMax=0; int calHistNum=0; int whiteContrast=0; int i,j,tmp; int his[256]; for(i= 0;i<256;i++) his[i] = 0; //calculate the histogram of image for(j=sWin.pt.y-sWin.h;j<sWin.pt.y+sWin.h;j++) { for(i=sWin.pt.x-sWin.w;i<sWin.pt.x+sWin.w;i++) { tmp = sGray[i*nWidth+j]; his[tmp]++; if(tmp>grayMax) grayMax = tmp; calHistNum++; } } //calculate the contrast of image for(i= 0;i<256;i++) { mean+=his[i]*i; } mean = mean/calHistNum; whiteContrast = 100*(grayMax-mean)/grayMax; if(whiteContrast>30) threshold = grayMax-50; else if (whiteContrast>27) threshold = grayMax-30; else if (whiteContrast>24) threshold = grayMax-20; else if (whiteContrast>20) threshold = grayMax-15; else if (whiteContrast>9) threshold = grayMax-11; else if (whiteContrast>4) threshold = grayMax-6; else threshold = grayMax; return threshold; } //利用目标面积求阈值 int CGravityCenter::GetWThByAera(unsigned char *sGray, WININFO sWin, int nWidth, int nHeight) { int threshold; int grayMax=0; int i,j,tmp; int his[256]; for(i= 0;i<256;i++) his[i] = 0; //calculate the histogram of image for(j=sWin.pt.y-sWin.h;j<sWin.pt.y+sWin.h;j++) { for(i=sWin.pt.x-sWin.w;i<sWin.pt.x+sWin.w;i++) { tmp = sGray[i*nWidth+j]; his[tmp]++; if(tmp>grayMax) grayMax = tmp; } } float rate=(sWin.w-EDGE_DRAW)*(sWin.h-EDGE_DRAW)+0.0f/(sWin.w*sWin.h); threshold = int(grayMax-grayMax*rate); return threshold; } //调整边界窗口 WININFO CGravityCenter::AdjustWindow(WININFO sWin, int sWidth, int sHeight) { WININFO win; CRect rt; rt.left = sWin.pt.x-sWin.w; rt.right = sWin.pt.x+sWin.w; rt.top = sWin.pt.y-sWin.h; rt.bottom = sWin.pt.y+sWin.h; if(rt.left<2) { rt.left = 2; rt.right = (sWin.pt.x+sWin.w)<42 ? 42:(sWin.pt.x+sWin.w); } if(rt.right>sWidth-2) { rt.right = sWidth-2; rt.left = (sWin.pt.x-sWin.w)>=(sWidth-42) ? (sWidth-42):(sWin.pt.x-sWin.w); } if(rt.top<2) { rt.top = 2; rt.bottom = (sWin.pt.y+sWin.h)<42 ? 42:(sWin.pt.y+sWin.h); } if(rt.bottom>sHeight-2) { rt.bottom = sHeight-2; rt.top = (sWin.pt.y-sWin.h)>=(sHeight-42) ? (sHeight-42):(sWin.pt.y-sWin.h); } win.w = (rt.right-rt.left)/2; win.h = (rt.bottom-rt.top)/2; win.pt.x = rt.left+win.w; win.pt.y = rt.top+win.h; win.flag = sWin.flag; return win; } //多目标跟踪中擦除目标 void CGravityCenter::erasure(unsigned char* sGray, WININFO sWin, int sWidth, int sHeight) { int i,j; for(j=sWin.pt.y-sWin.h;j<sWin.pt.y+sWin.h;j++) { for(i=sWin.pt.x-sWin.w;i<sWin.pt.x+sWin.w;i++) { int k = sWidth*j+i; sGray[k] = (unsigned char)0; } } } //重心跟踪 WININFO CGravityCenter::gvtrack(unsigned char* sGray,int sWidth, int sHeight, WININFO sWin, int sThreshold) { WININFO win; win.w = 0; win.h = 0; win.pt.x = 0; win.pt.y = 0; win.flag = FALSE; int M00bh = 0; int M01bh = 0; int M10bh = 0; int i,j,iLine;//iCol; for(j=sWin.pt.y-sWin.h;j<sWin.pt.y+sWin.h;j++) { iLine = 0; for(i=sWin.pt.x-sWin.w;i<sWin.pt.x+sWin.w;i++) { int k = sWidth*j+i; if(sGray[k]>sThreshold) { iLine++; M01bh+=i; M10bh+=j; } } M00bh+=iLine; if(win.w<iLine) win.w = iLine; if(iLine>3) win.h++; } if(M00bh>10) { win.pt.x = int(M01bh/M00bh+0.5); win.pt.y = int(M10bh/M00bh+0.5); win.w = win.w/2+EDGE_DRAW; win.h = win.h/2+EDGE_DRAW; win.flag = TRUE; } return win; } //投影找最大值法 WININFO CGravityCenter::project(unsigned char* sGray, int sWidth, int sHeight, int sThreshold) { WININFO win; win.w = 0; win.h = 0; win.pt.x = 0; win.pt.y = 0; win.flag = FALSE; int X_MaxLocation=0, X_MaxLength=0; int Y_MaxLocation=0, Y_MaxLength=0; int *row, *column; row = new int[sWidth]; column = new int[sHeight]; memset(row,0,sWidth*sizeof(int)); memset(column,0,sHeight*sizeof(int)); int i,j,t; for(j=EDGE_SPACE; j<sWidth-EDGE_SPACE; j++) { for (i=EDGE_SPACE; i<sHeight-EDGE_SPACE; i++) { int k = i*sWidth+j; if(sGray[k]>sThreshold) row[j] = 1; } } for(i=EDGE_SPACE; i<sHeight-EDGE_SPACE; i++) { for (j=EDGE_SPACE; j<sWidth-EDGE_SPACE; j++) { int k = i*sWidth+j; if(sGray[k]>sThreshold) column[i] = 1; } } int location=0; int count=0; int length=0; for(t=0; t<sWidth; t++) { if(row[t] == 1) { count++; length = count; location = t-length+1; } else { count = 0; if(length>X_MaxLength) { X_MaxLocation = location; X_MaxLength = length; } } } location=0; count=0; length=0; for(t=0; t<sHeight; t++) { if(column[t] == 1) { count++; length = count; location = t-length+1; } else { count = 0; if(length>Y_MaxLength) { Y_MaxLocation = location; Y_MaxLength = length; } } } delete []row; delete []column; win.pt.x = int(X_MaxLocation+X_MaxLength/2+0.5); win.pt.y = int(Y_MaxLocation+Y_MaxLength/2+0.5); win.w = X_MaxLength/2+EDGE_DRAW; win.h = Y_MaxLength/2+EDGE_DRAW; if((X_MaxLength+Y_MaxLength)>5) win.flag = TRUE; return win; } //重心法 WININFO CGravityCenter::gravity(unsigned char* sGray, int sWidth, int sHeight, int sThreshold) { WININFO win; win.w = 0; win.h = 0; win.pt.x = 0; win.pt.y = 0; win.flag = FALSE; int M00bh = 0; int M01bh = 0; int M10bh = 0; int iLine,i,j; for(j=EDGE_SPACE;j<sHeight-EDGE_SPACE;j++) { iLine = 0; for(i=EDGE_SPACE;i<sWidth-EDGE_SPACE;i++) { int k = sWidth*j+i; if(sGray[k]>sThreshold) { iLine++; M01bh+=i; M10bh+=j; } } M00bh+=iLine; if(win.w<iLine) win.w = iLine; if(iLine>0) win.h++; } if(M00bh>10) { win.pt.x = int(M01bh/M00bh+0.5); win.pt.y = int(M10bh/M00bh+0.5); win.w = win.w/2+EDGE_DRAW; win.h = win.h/2+EDGE_DRAW; win.flag = TRUE; } return win; } //找边法 WININFO CGravityCenter::findEdge(unsigned char* sGray, int sWidth, int sHeight, int sThreshold, int sBlockNum) { WININFO win; win.w = 0; win.h = 0; win.pt.x = 0; win.pt.y = 0; win.flag = FALSE; int blockH = sHeight/sBlockNum; int x=0,w=0,n=0; int i,j,t=0; int tStart, tEnd; int *row = new int[sWidth]; while(n<sBlockNum) { memset(row,0,sWidth*sizeof(int)); for(j=EDGE_SPACE; j<sWidth-EDGE_SPACE; j++) { for (i=n*blockH; i<(n+1)*blockH; i++) { int k = i*sWidth+j; if(sGray[k]>sThreshold) row[j] = 1; } } for(t=0;t<sWidth;t++) { if(row[t]==1) { tStart=t; while(row[t]!=0) t++; tEnd = t; w = (tEnd-tStart)/2; if(w>1) { x = tStart+(tEnd-tStart)/2; break; } } } if(x>2) { win.pt.x = x; win.pt.y = n*blockH+blockH/2; win.w = w+10; win.h = blockH/2; win.flag = TRUE; break; } else n++; } delete []row; row = NULL; return win; }